类型提示 -Stubs
类型提示 -Stubs
官方文档:Stub Files
Pycharm 中队 Stubs 的支持:Stubs | PyCharm Documentation
参考文档:Python Stubs
模块骨架文件,后缀为 pyi
,文件名要跟其描述的模块的文件名相同,用于声明其描述的模块的所有的变量,方法,类型,声明这些类型的存在,和他们的类型,其实主要是声明类型,
在 Pycharm 中拥有 stubs 文件的模块的方法或者类的左侧会有一个星号,用于在模块和其 stubs 文件之间相互跳转,
其实你可以将类型信息直接写在模块文件中,而不是用一个专门的 pyi 文件村,但是 python2 和 python3 的方式不一样,因为 Python2.x 与 3.x 版本并不兼容
python2:代码注释
python3:类型注解
具体请看《类型提示.md》
一般情况下 stubs 文件会与其修饰的模块处在同一目录,但是如果需要修饰的模块是下载的第三方模块,我们就需要新建同样的目录来存放 stubs 文件像这样。
请参考:Stubs | PyCharm Documentation | Create a stub file for the external implementation

其实我们不使用 stubs 文件,这样我们也可以直接 import 包中的模块,然后使用其变量和方法。但是创建了模块对应的 stubs 文件之后,我们就会以 stubs 文件中的信息为准,如果 stubs 文件中故意没有写其描述的模块中的某一个方法或者变量或者类,那么在 import 这个模块之后,我们将无法使用这个漏掉的方法或者变量或者类。
stubs 文件的功能:
-
我们可以通过向没有类型注解(type annotations)的第三方库添加单独的 stubs 文件来添加类型信息。对于那些在进行大量类型推断时具有高负载的大型模块,使用 stubs 文件可以减少负载并减少代码编辑的手自动补全和类型检查等延迟。
然后我们就有了公用的 stubs 文件包 Typeshed:Typeshed 是一组带有Python 标准库和各种包的类型注释的文件。Typeshed 的 stubs 文件为 Python 类、函数和模块提供定义,在定义中增加类型提示信息。Pycharm 内置了 Typeshed。PyCharm 使用这些信息来实现更好的代码完成、检查和其他代码洞察功能。
我们还可以自动生成 stubs 文件,比如通过
mypy
模块的的stubgen
工具 -
实现编辑器的类型提示,类型检查,在没有创建 stubs 文件的时候,导入模块之后使用模块中的方法或者变量,是没有类型提示的,只有变量名提示,但是有了 stubs 文件之后,就可以根据 stubs 文件中的类型信息进行提示,如果类型不匹配,会警告,但是不报错
-
隐藏你不想要别人看到的方法或者变量,当然如果别人就是知道有这个方法,然后在 stubs 文件中没有声明这个方法的时候调用这个方法,解释器会报错,但是可以正常运行。
简单实践
首先准备一下包结构
xyz 包和 xiashuo 包的 __init__.py
文件文件都是空的,重点看 str_function.py
:
name = "xiashuo"
age = 12
def str_greeting():
print(f"Hello {name}")
def show_info(name, age):
print(f"hello everyone , I am {name}, i am {age} years old")
和 str_function.pyi
:
def str_greeting() -> None: ...
# 在pyi中定义方法的类型信息跟直接在py中定义方法的类型信息在语法上的唯一的区别就是在pyi中方法体部分用 ... 代替
# 在这里声明方法和参数类型之后,使用这个方法的时候,就会有型提示
def show_info(name: str, age: int) -> None: ...
在 pyi 中定义方法的类型信息跟直接在 py 中定义方法的类型信息在语法上的唯一的区别就是在 pyi 中方法体部分用 ...
代替
在 .pyi
文件也就是 stubs 文件中声明变量的类型方法的参数和返回值类型之后,使用这个变量和方法的时候,就会有型提示。调用方法的时候传入的类型不对,也会有提示
测试代码如下:
from xyz.xiashuo.str_function import *
print(name)
print(age)
# 如果stubs中没有声明这个方法,在这里,解释器会报错,但是依然可以成功运行
str_greeting()
show_info("sdf", 12)
# 虽然类型跟stubs中的类型不匹配,但仅仅是警告,没有报错
show_info("dfdfa", "dfsd")
在 Pycharm 中,因为我们没有在 str_function.pyi
中声明 name 和 age 这两个变量,因此在导入后,解释器不知道这两个变量的含义,因此报错,但是不会阻止运行,而且在 str_function.py
中实际上是有这两个变量的,因此实际执行不会报错
在 .pyi
文件中,show_info
的第二个参数应该是 int,但是传入了 str,会有警告,但是不会阻止运行
输出:
xiashuo
12
Hello xiashuo
hello everyone , I am sdf, i am 12 years old
hello everyone , I am dfdfa, i am dfsd years old
从这里我们可以看到在 Python 中,类型信息的严格匹配,并不是程序执行的必要条件,即使类型不对,解释器也不会阻止代码的运行。从这个角度看类型信息确实是可有可无的
总结
如果你本身就偏向于编写带有类型信息的 python 代码,那么类型注解是你的首选,而不是 stubs 文件,stubs 文件只能作为一种之前没写类型信息,后面想补上的补救措施。
请参考《类型提示 - 类型注解.md》